//---------------------------------------------------------------------------
#ifndef CBackupRH
#define CBackupRH
//---------------------------------------------------------------------------
#include "Outils.h"
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>


#include <dir.h>
#include <limits.h>
#include <time.h>
#include "FBarProgress.h"

// Extension par défaut d'un fichier de Backup/Restore
#define BR_DEFAULT_BRFILE_EXT ".BR"

// TAG de l'en-tête d'un fichier Backup/Restore
#define BR_HEADER_TAG 0x7485

// Espace libre minimum requis sur une disquette pour faire un backup
#ifdef ANCIEN_BR
  #define BR_MIN_BACKUP_FLOPPY_FREE_SPACE ( 64L * 1024L )
#else
  #define BR_MIN_BACKUP_FLOPPY_FREE_SPACE (unsigned __int64)( 64L * 1024L )
#endif

// Taille du buffer d'IO pour Backup/Restore
#ifdef ANCIEN_BR
  #define BR_IO_BUFSIZE ((unsigned short int)( USHRT_MAX - 32))
#else
  #define BR_IO_BUFSIZE          (DWORD)((DWORD)128 * (DWORD)1024)
#endif

// Valeurs possibles pour BR_FILEDESC.uhFlags (Cf. BR_ON_RESTORE_FILE)
#define FDF_NULL       0x0000
#define FDF_COMPRESSED 0x0001

#define DELETE_FLOPPY_FILES_BEFORE_BACKUP
#ifdef ANCIEN_BR
  #define KEEP_BYTES_ON_FIRST_FLOPPY        ( 3 * 512 )
#else
  #define KEEP_BYTES_ON_FIRST_FLOPPY      (unsigned __int64)(   3 *  512  )
#endif


#define NUM_VERS_1		1
#define NUM_VERS_2		0


#define NB_CODES_RET 17

////////////////////////////////////////////////
//// Types utilisés pour les Backup/Restore ////
////////////////////////////////////////////////

// En-tête d'un fichier BR
#pragma pack( 1 )
typedef struct tagBR_HEADER
	{
  	unsigned short Tag;            // Tag du fichier ( BR_HEADER_TAG)
  	unsigned short NumVer;         // Version du fichier BR
  	time_t         tiBackup;       // Date/Heure de création du backup
  	unsigned short NumDisk;        // N° du disque (>=1)
  	unsigned short UserNumVer;     // Version fonction utilisateur de gestion du BR
  	unsigned char  sRFU[ 20 ];     // Reserved for Futur Usage
	}BR_HEADER;
#pragma pack()


// Structure utilisée pour Restaurer un fichier (Cf. BR_ON_RESTORE_FILE)
#pragma pack(1)
typedef struct tagBR_FILEDESC
	{
	long           lSize;        // File's Size
	long           lCmpSize;     // Compressed file's size
	unsigned short fAttrib;      // File's Attributes
	unsigned short uhLMDate;     // Last Modified Date
	unsigned short uhLMTime;     // Last Modified Time
	unsigned short uhFlags;      // Drapeaux pour utilisation interne (FDF_*)
	char           pszName[MAXPATH];   // File's name
	}BR_FILEDESC;
#pragma pack()


typedef struct
	{
	int         nImplodeSize;
	TFileStream *pWStream;
	TFileStream *pRStream;
	}TWriteParams;


////////////////////////////////////////////////
//// Code d'action/Erreur utilisées pour BR ////
////////////////////////////////////////////////
typedef enum BR_CODETag
	{
  	BR_OK               = 0,        // Pas d'erreur
  	BR_REDO,                        // Interne
  	BR_STOP,                        // Interne
  	BR_ERR_ACTION_CANCELED,         // Suite à ordre utilisateur
  	BR_ERR_EXHAUSTED_MEMORY,
  	BR_ERR_BR_PATH_NOT_FOUND,
  	BR_ERR_NO_SRC_FILE_TO_BACKUP,
  	BR_ERR_TMP_FILE_ACCESS_IO_ERROR,
 	BR_ERR_IMPLODING_FILE,
  	BR_ERR_EXPLODING_FILE,
  	BR_ERR_DEST_FILE_WRITE_ERROR,
  	BR_ERR_SRC_FILE_READ_ERROR,
  	BR_ERR_SRC_FILE_DELETED_DURING_BACKUP,
  	BR_ERR_BR_FILE_CORRUPTED,  // Déclenché seulement lors d'un EICRestore
	BR_ERR_DRIVE_UNKNOW,
  	BR_ERR_DRIVE_PROTECT,
    BR_ERR_DRIVE_OUTOFSPACE
  	}BR_CODE;


typedef enum TListEventBRTag
	{
	eBRBeginBackup,
	eBRBeginRestore,
	eBRInsertFloppy,
	eBRGetPatternToBackup,
	eBRPercents,
	eBRRestorePattern,
	eBRError,
	eBRHardError,
	eBREnd
	}TListEventBR;

typedef Set<TListEventBR, eBRBeginBackup, eBREnd> TListEventsBR;



class PACKAGE_OUTILS CBackupRestore : public TComponent
	{
	private:
		typedef void __fastcall (__closure *TBeginBackupEvent)(			TObject 			*Sender,
																		Word 	 			MaxSizeUserDesc,
																		Word      			&SizeUserDesc,
																		DWORD		        &pvUserDesc,
																		Word 	 			&HiNumVers,
																		Word				&LoNumVers );

	   typedef void __fastcall (__closure *TBeginRestoreEvent)(			TObject 			*Sender,
																		Word	 			SizeDatas,
																		const void		 	*pvUserDesc,
																		Word	 			HiNumVers,
																		Word	 			LoNumVers,
																		bool               	&Abort );
		typedef void __fastcall (__closure *TInsertFloppyEvent)(		TObject 			*Sender,
																		int 				NumDisk,
																		const AnsiString  	&FilePath,
																		bool 	  			&Abort,
																		bool 	  			Backup );

	   typedef void __fastcall (__closure *TNewFloppyEvent)(			TObject 			*Sender,
																		Word 	    		NumFloppy,
																		const AnsiString  	&FileName,
																		bool 		  	    Backup );

	   typedef void __fastcall (__closure *TBackupMediaReadyEvent)(		TObject 			*Sender,
																		Word 	 			NumFloppy,
																		const AnsiString 	&PathBackup,
																		bool 	         	&Abort );

	   typedef void __fastcall (__closure *TGetPatternToBackupEvent)(	TObject 			*Sender,
																		Word  				MaxSizeUserDesc,
																		Word 				&SizeUserDesc,
																		DWORD	 			&pvUserDesc,
																		AnsiString  		&PathPattern,
																		bool           		&Abort );

	   typedef void __fastcall (__closure *TBackupFileEvent)(			TObject 			*Sender,
																		const AnsiString 	&FileName );



	   typedef void __fastcall (__closure *TPercentsEvent)(				TObject 			*Sender,
																		Word 	    		BRPercents,
																		Word 	    		PatternPercents,
																		Word     			FilePercents,
																		bool			 	Backup );

	   typedef void __fastcall (__closure *TRestorePatternEvent)(		TObject 			*Sender,
																		int 	 			SizePattern,
																		Word				NbPatternFiles,
																		bool             	&bDoNotRestore,
																		Word   				&uhUserDataLen,
																		void    			*pvUserDesc,
																		AnsiString  	&PathPattern,
																		bool             	&Abort );

	   typedef void __fastcall (__closure *TRestoreFileEvent)(			TObject 			*Sender,
																		BR_FILEDESC    	 	&psFileDesc,
																		AnsiString	&PathRestore,
																		bool				&Abort );

	   typedef void __fastcall (__closure *TErrorEvent)(				TObject 			*Sender,
																		BR_CODE 	    	NumError,
																		const AnsiString	&Msg,
																		bool				Backup );

	   typedef void __fastcall (__closure *THardErrorEvent)(			TObject 			*Sender,
																		BR_CODE				NumError,
																		const AnsiString	&Msg,
																		bool				&Abort,
																		bool  				Backup );

	   typedef void __fastcall (__closure *TEndEvent)(					TObject 			*Sender,
																		BR_CODE				CodeRet,
																		const AnsiString 	&Msg,
																		bool 				Backup );

		TBeginBackupEvent			FOnBeginBackup;
		TBeginRestoreEvent			FOnBeginRestore;
		TInsertFloppyEvent			FOnInsertFloppy;
		TNewFloppyEvent				FOnNewFloppy;
		TBackupMediaReadyEvent  	FOnBackupMediaReady;
		TGetPatternToBackupEvent	FOnGetPatternToBackup;
		TBackupFileEvent			FOnBackupFile;
		TPercentsEvent				FOnPercents;
		TRestorePatternEvent		FOnRestorePattern;
		TRestoreFileEvent			FOnRestoreFile;
		TErrorEvent					FOnError;
		THardErrorEvent				FOnHardError;
		TEndEvent					FOnEnd;

		AnsiString				FDirectory;
		AnsiString				FBRDirectory;
		AnsiString				FBRFileName;
		TListEventsBR			FAutoEvents;
		bool						FSubDirectory;

		TFileStream 	*FBackup;
		TFileStream 	*FCmpDst;
		TFileStream 	*FCmpSrc;

		bool 			bForBackup;
		bool 			bIsBROnFloppy;
		bool			bDeleteFilesBeforeBackup;

		long       		lBRUserData;
		__int64			lBRLeftSize;
		long        	lLeftFileSize;
		long        	lCurDataSize;       // Nb octets du pattern déjà backupés
		unsigned int   	uSrcBlockSize;   // Taille d'un bloc de fhSrc à backuper
		long 			lCmpSrcSize;
		long 			lCmpDstSize;
		long			lAllFilesBR;

		BR_HEADER		brHeader;

		AnsiString 		aSrcPathPattern;
		AnsiString 		aBRFilePath;
		AnsiString 		aBRFileName;

		unsigned char 	*IOBuffer;

		TStringList		*ListPathToBackup;
		int				IemIndexListPathToBackup;

   __published:
		__property AnsiString 				Directory	 			= { read=FDirectory, 		 	write=SetDirectory		};
		__property AnsiString 				BRDirectory	 			= { read=FBRDirectory, 		 	write=SetBRDirectory		};
		__property AnsiString 				BRFileName				= { read=FBRFileName, 		 	write=SetBRFileName		};
		__property TListEventsBR			AutoEvents				= { read=FAutoEvents, 		 	write=SetAutoEvents 		};
		__property bool 					   SubDirectory			= { read=FSubDirectory, 	 	write=FSubDirectory		};

		__property TBeginBackupEvent		OnBeginBackup			= { read=FOnBeginBackup, 		write=FOnBeginBackup		};
		__property TBeginRestoreEvent		OnBeginRestore			= { read=FOnBeginRestore, 		write=FOnBeginRestore		};
		__property TInsertFloppyEvent 		OnInsertFloppy 			= { read=FOnInsertFloppy, 		write=FOnInsertFloppy		};
		__property TNewFloppyEvent			OnNewFloppy				= { read=FOnNewFloppy, 			write=FOnNewFloppy			};
		__property TBackupMediaReadyEvent  	OnBackupMediaReady		= { read=FOnBackupMediaReady, 	write=FOnBackupMediaReady	};
		__property TGetPatternToBackupEvent	OnGetPatternToBackup	= { read=FOnGetPatternToBackup, write=FOnGetPatternToBackup	};
		__property TBackupFileEvent			OnBackupFile			= { read=FOnBackupFile, 		write=FOnBackupFile			};
		__property TPercentsEvent			OnPercents				= { read=FOnPercents, 			write=FOnPercents			};
		__property TRestorePatternEvent		OnRestorePattern		= { read=FOnRestorePattern, 	write=FOnRestorePattern		};
		__property TRestoreFileEvent		OnRestoreFile			= { read=FOnRestoreFile, 		write=FOnRestoreFile		};
		__property TErrorEvent				OnError					= { read=FOnError, 				write=FOnError				};
		__property THardErrorEvent			OnHardError 			= { read=FOnHardError, 			write=FOnHardError			};
		__property TEndEvent				OnEnd					= { read=FOnEnd, 				write=FOnEnd				};

   private:
		// Evenements internes dans le cas ou ils n'ont pas ete definis par le programmeur
		void __fastcall OnOwnPercents(				TObject 			*Sender,
													Word 	    		BRPercents,
													Word 	    		PatternPercents,
													Word     			FilePercents,
													bool			 	Backup );

		void __fastcall OnOwnInsertFloppy( 			TObject 		   	*Sender,
													int 				NumDisk,
													const AnsiString &FilePath,
													bool 	  			&Abort,
													bool 	  			Backup );

		void __fastcall OnOwnGetPatternToBackup(	TObject 			*Sender,
													Word  				MaxSizeUserDesc,
													Word 				&SizeUserDesc,
													void	 			*pvUserDesc,
													AnsiString     		&PathPattern,
													bool           		&Abort );

		void __fastcall OnOwnError(	 				TObject 			*Sender,
													BR_CODE 	    	NumError,
													const AnsiString &Msg,
													bool				Backup );

		void __fastcall OnOwnHardError(				TObject 			*Sender,
													BR_CODE				NumError,
													const AnsiString &Msg,
													bool				&Abort,
													bool  				Backup );

		void __fastcall OnOwnEnd(	  				TObject 			*Sender,
													BR_CODE				CodeRet,
													const AnsiString &Msg,
													bool 				Backup );


		void		__fastcall SetDirectory( 	const AnsiString		&aNewDirectory 	);
		void		__fastcall SetBRDirectory( 	const AnsiString		&aNewDirectory 	);
		void		__fastcall SetBRFileName( 	const AnsiString		&aNewFileName 	);
		void		__fastcall SetAutoEvents(	TListEventsBR 	NewAutoEvents 	);

		BR_CODE 	__fastcall BRBegin(const AnsiString &aBRFilePath,const AnsiString &aBRFileName);
		void 	  	__fastcall BREnd();
		BR_CODE 	__fastcall BRInsertFloppy();
		BR_CODE 	__fastcall BackupBuffer( 	void *Datas,    long lLenDatas );
		BR_CODE 	__fastcall BackupBuffer( 	TFileStream *F, long lLenDatas );
		BR_CODE 	__fastcall RestoreBuffer( 	void *Datas,   	long lLenDatas );
		BR_CODE 	__fastcall BackupPattern( 	unsigned short 		uhUserDataLen,
												const unsigned char *sUserDesc );
		BR_CODE 	__fastcall RestorePattern( 	unsigned short 		&uhUserDataLen,
												unsigned char 		*sUserDesc,
											   const AnsiString			&aTmpFile );
		BR_CODE 	__fastcall CopieBuffer( 	TFileStream *Sour, TFileStream *Dest, long lLenDatas );

		int			__fastcall GetCodeErr( const AnsiString &aErrName );

		BR_CODE 	__fastcall CloseStreamBackup();
		void 		__fastcall DeleteFilesBeforeBackup();
		bool 		__fastcall IsDiskSizeOk(const AnsiString &aPath,	BR_CODE &eRetCode );
		bool   		__fastcall BRIsGoodBRFile( 	 const	AnsiString 		&aBRFile		);
		BR_CODE 	__fastcall DriveStatus(const AnsiString &aDir);
		void 		__fastcall OpenBR( 				BR_CODE 		&eRetCode 	);
		void 		__fastcall GetSubDirectories( 	const AnsiString 		&aPath );

		AnsiString	__fastcall MakeFullFile( const	AnsiString 		&Path,  const	AnsiString &File );

		BR_CODE 	__fastcall BRImplodeFile();
		BR_CODE 	__fastcall BRExplodeFile(	TFileStream *FDst);

	public:
		__fastcall CBackupRestore(TComponent* Owner);

		BR_CODE  	__fastcall Backup();
		BR_CODE 	__fastcall Restore();

		virtual __fastcall ~CBackupRestore();
	};


#endif
 
